package dames;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

import org.omg.CORBA.ORB;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;

import dames.gen.Pion;
import dames.gen.PionHelper;
import dames.gen.deplacementPionException;
import dames.gen.enumCouleurs;
import dames.gen.gestionnaire_de_parties;
import dames.gen.gestionnaire_de_partiesHelper;
import dames.gen.joueurHelper;
import dames.gen.joueurPOA;
import dames.gen.nomDePartieInexistant;
import dames.gen.nomDePartieReserve;
import dames.gen.partie;
import dames.gen.partieNonDisponible;
import dames.gen.partieOperations;
import dames.gen.partiePackage.enumEtat;

class joueurImpl extends joueurPOA {
	private String nom_du_joueur;
	private enumCouleurs couleur;
	private boolean a_moi_de_jouer;
	
	public joueurImpl(String nom_du_joueur){
		this.nom_du_joueur = nom_du_joueur;
	}

	@Override
	public void a_toi_de_jouer(){
		a_moi_de_jouer = true;
	}

	@Override
	public void partie_gagnee(){
		
	}

	@Override
	public void partie_perdue(){
		
	}

	@Override
	public String nom_du_joueur(){
		return nom_du_joueur;
	}
	
	@Override
	public void attends() {
		a_moi_de_jouer = false;
	}
	
	public boolean isAMoiDeJouer(){
		return a_moi_de_jouer;
	}

	public static gestionnaire_de_parties connexionServeur(ORB orb){
		 String ior = null;

	        try {
	            String ref = "gestion.ref";
	            FileInputStream file = new FileInputStream(ref);
	            BufferedReader in = new BufferedReader(new InputStreamReader(file));
	            ior = in.readLine();
	            file.close();
	        } catch (IOException ex) {
	            System.err.println("Impossible de lire fichier : `" +
	                ex.getMessage() + "'");
	            System.exit(1);
	        }
	        
	        org.omg.CORBA.Object obj = orb.string_to_object(ior);

	        if (obj == null) {
	            System.err.println("Erreur sur string_to_object() ");
	            throw new RuntimeException();
	        }

	        return gestionnaire_de_partiesHelper.narrow(obj);
	}
	
	private static void affichePlateau(Pion[][] plateau){
		System.out.print(" ");
		for(int i = 0; i < partieOperations.LARGEUR_PLATEAU; i++) System.out.print(" "+i);
		System.out.println();
		for(int y = 0; y < partieOperations.HAUTEUR_PLATEAU; y++){
			System.out.print(y);
			for(int x = 0; x < partieOperations.LARGEUR_PLATEAU; x++){
				if(plateau[y][x] == null){
					if((x % 2) + (y % 2) == 1)	System.out.print(" #");
					else						System.out.print(" _");
				}else{
					if(plateau[y][x].couleur == enumCouleurs.BLANC)	System.out.print(" ○");
					else											System.out.print(" ●");
				}
			}
			System.out.println();
		}
	}
	
	public static void main(String[] args) throws IOException {
		Orb_Run orbRun = null;
		gestionnaire_de_parties gestparties = null;
		partie partie = null;
		String nomJoueur = null;
		String nomPartie = null;
		

		try {
			//init ORB
			orbRun = new Orb_Run(ORB.init(args, null));
			
			Scanner sc = new Scanner(System.in);
			System.out.println("Veuillez entrer votre nom :");
			nomJoueur = sc.nextLine();
			
			//init POA
			POA poa = POAHelper.narrow(orbRun.getOrb().resolve_initial_references("RootPOA"));
			poa.the_POAManager().activate();

			////////////////////////////////////////////////////////////////
			joueurImpl joueurimpl = new joueurImpl(nomJoueur);
			org.omg.CORBA.Object joueur = poa.servant_to_reference(joueurimpl);

			try {
				String joueur_ref = orbRun.getOrb().object_to_string(joueur);
				String refFile = nomJoueur+".ref";
				PrintWriter out = new PrintWriter(new FileOutputStream(refFile));
				out.println(joueur_ref);
				out.close();
			} catch (IOException ex) {
				System.err.println("Impossible d'ecrire la reference dans "+nomJoueur+".ref");
				System.exit(1);
			}

			orbRun.start();

			gestparties = connexionServeur(orbRun.getOrb());
			
			boolean retourMenu = false;
			do{
				int choix;
				System.out.println("Que voulez vous faire ?");
				System.out.println("1 - Créer une partie.");
				System.out.println("2 - Rejoindre une partie.");
				System.out.println("3 - Lister les parties.");
				
				
				choix = Integer.parseInt(sc.nextLine());
				//choix = sc.nextInt();
				
				boolean err = false;
				switch(choix){
					case 1:
						
						do{
							err = false;
							System.out.println("Création d'une partie, veuillez entrer le nom de la partie :");
							
							nomPartie = sc.nextLine();
							
							try {
								partie = gestparties.creation_d_une_partie(joueurHelper.narrow(joueur), nomPartie);
							} catch (nomDePartieReserve e) {
								System.err.println("Ce nom de partie est déjà réservé");
								err = true;
							}
							
						}while(err);
						System.out.println("Vous prenez les pions blancs,\nattente d'un autre joueur...");
						
						retourMenu = false;
						break;
					case 2:
						
						do{
							err = false;
							System.out.println("Veuillez entrer le nom de la partie que vous souhaitez rejoindre :");
		
							nomPartie = sc.nextLine();
							
							try {
								partie = gestparties.ajouter_joueur_pions_noirs(joueurHelper.narrow(joueur), nomPartie);
							} catch (nomDePartieInexistant e) {
								System.err.println("Cette partie n'existe pas");
								err = true;
							} catch (partieNonDisponible e) {
								System.err.println("Cette partie n'est plus disponible");
								err = true;
							}
						
						} while(err);
						System.out.println("Vous prenez les pions noirs");
						
						retourMenu = false;
						break;
					case 3:
						
						ArrayList<String> lnp = new ArrayList<String>(Arrays.asList(gestparties.listeNomsParties()));
						for (String nom : lnp) {
							System.out.println(nom);
						}
						
						retourMenu = true;
						break;
					default:
						System.err.println("Choix incorrect");
						
						retourMenu = true;
				}
			} while(retourMenu);
			
			while(partie.etat() != enumEtat.TERMINEE){
				Thread.sleep(1000);
				if(joueurimpl.isAMoiDeJouer()){
					System.out.println("C'est à moi de jouer !");
					
					Pion[] listePions = partie.pions();
					Pion[][] plateau = new Pion[partieOperations.HAUTEUR_PLATEAU][partieOperations.LARGEUR_PLATEAU];
					for(int i = 0; i < listePions.length; i++) plateau[listePions[i].y][listePions[i].x] = listePions[i]; 
					affichePlateau(plateau);
					
					Pion pionADeplacer = null;
					boolean err;
					do{
						do{
							err = false;
							
							System.out.println("Saisir les coordonnées du pion à déplacer : x y");
							int x = sc.nextInt();
							int y = sc.nextInt();
							if(x >= partieOperations.LARGEUR_PLATEAU &&
									x < 0 &&
									y >= partieOperations.HAUTEUR_PLATEAU &&
									y < 0) err = true;
							else{
								pionADeplacer = plateau[y][x];
							}
							if(pionADeplacer == null) err = true;
							if(err) System.err.println("Mauvais choix, recommencez");
						} while(err);
						
						err = false;
						System.out.println("Saisir les coordonnées d'arrivée : x y");
						int x = sc.nextInt();
						int y = sc.nextInt();
						
						try {
							partie.faire_un_deplacement(pionADeplacer.id, x, y, joueurHelper.narrow(joueur));
						} catch (deplacementPionException e) {
							// TODO Auto-generated catch block
							System.err.println(e.message);
							err = true;
						}
					} while(err);
					
					listePions = partie.pions();
					plateau = new Pion[partieOperations.HAUTEUR_PLATEAU][partieOperations.LARGEUR_PLATEAU];
					for(int i = 0; i < listePions.length; i++) plateau[listePions[i].y][listePions[i].x] = listePions[i]; 
					affichePlateau(plateau);
				}
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

}
